<?php

namespace app\services\wechat;


use app\common\model\Config;
use think\Exception;
use think\facade\Log;


class Miniprogram
{

    public function __construct(){

        $config = [
            'appid' => Config::getConfigValue('xcx_appid'),
            'appSecret' => Config::getConfigValue('xcx_appSecret'),
            'mchid' => Config::getConfigValue('xcx_mch_id'),
            'key_file' => Config::getConfigValue('xcx_key_file'),
            'cret_file' => Config::getConfigValue('xcx_cret_file'),
            'serial_number' => Config::getConfigValue('xcx_serial_number'),
            'm_appSecret' => Config::getConfigValue('xcx_m_appSecret'),
            'sp_appid' => Config::getConfigValue('xcx_sp_appid'),
            'sp_mchid' => Config::getConfigValue('xcx_sp_mchid'),
            //'sub_appid' => Config::getConfigValue('gzh_sub_appid'),
            'sub_mchid' => Config::getConfigValue('xcx_sub_mchid'),
            'm_key_file' => Config::getConfigValue('xcx_m_key_file'),
            'm_cret_file' => Config::getConfigValue('xcx_m_cret_file'),
            'm_serial_number' => Config::getConfigValue('xcx_m_serial_number'),
            'pay_type' => Config::getConfigValue('pay_type'),
        ];
        $this->config=$config;
    }
    public  function getAccessToken(){
        $data['access_token'] = cache('access_token');
        if ($this->config['pay_type'] == 1){
            $appid = $this->config["appid"];
            $appSecret = $this->config["appSecret"];
        }else{
            $appid = $this->config["sp_appid"];
            $appSecret = $this->config["m_appSecret"];
        }
        if ($data['access_token']) {
            return $data['access_token'];
        }else{
            $url_get = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" .$appid . "&secret=" . $appSecret;
            $data = curlGet($url_get);
            $output = json_decode($data, true);
            if (!isset($output['access_token'])){
                throw new Exception('接口调用凭据失败');
            }
        }
        return $output['access_token'];
    }
    public function getUserInfo($encryptedData,$iv,$session_key,$return){
        if ($this->config['pay_type'] == 1){
            $appid = $this->config["appid"];
            $appSecret = $this->config["appSecret"];
        }else{
            $appid = $this->config["sp_appid"];
            $appSecret = $this->config["m_appSecret"];
        }
        $WXBizDataCrypt =new Wxbizdatacrypt($appid,$session_key);
        $errCode    = $WXBizDataCrypt->decryptData($encryptedData,$iv,$return);
        $return=json_decode($return, true);
        return $return;
    }
    public function getPhone($code){
        $access_token = $this->getAccessToken();
        $url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=".$access_token;
        $data = [
            'code' => $code,
        ] ;
        $res = curlPost($url,json_encode($data)) ;
        $output=json_decode($res,true);
        return $output;

    }
    public function wechatpay($array, $openid, $title , $notify_url)
    {
        try {
            $appid = $this->config['appid'];//
            $mchid = $this->config['mchid'];;//商户id
            $xlid = $this->config['serial_number'];//证书序列号
            $time = time(); //时间戳
            $orderid = $array['order_sn'];//订单编号
            $noncestr = md5($orderid . $time . rand());//随机字符串，可以将订单编号存于此处
            $ordertotal = $array['price'] * 100;//
            $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';//生成预支序号所提交路径
            $urlarr = parse_url($url); //路径拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/jsapi]
            $data = array();
            $data['appid'] = $appid;
            $data['mchid'] = strval($mchid);
            $data['description'] = $title;//商品描述
            $data['out_trade_no'] = $orderid;//订单编号
            $data['notify_url'] = getProtocol() . $_SERVER["HTTP_HOST"] . '/home.php/' . $notify_url;//回调接口，可以为空
            $data['amount']['total'] = (integer)$ordertotal;//金额 单位 分
            $data['amount']['currency'] = 'CNY';
            $data['payer']['openid'] = $openid;//openid
            $jsonData = json_encode($data); //变为json格式
            $str = "POST" . "\n" . $urlarr['path'] . "\n" . $time . "\n" . $noncestr . "\n" . $jsonData . "\n";
            $signHead = $this->getPrivateSign($str,$this->config['key_file']);
            $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $noncestr, $time, $signHead);

            $header = array(
                'Content-Type:application/json; charset=UTF-8',
                'Accept:application/json',
                'User-Agent:*/*',
                'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $token
            );
            $res = $this->httpRequest($url, $jsonData, $header);
            $dataArray = json_decode($res, true);

            if (isset($dataArray['prepay_id'])) {
                $prepayID = $dataArray['prepay_id'];
                $prepay = 'prepay_id=' . $prepayID;
                $str = $appid . "\n" . $time . "\n" . $noncestr . "\n" . $prepay . "\n";
                $signPay = $this->getPrivateSign($str,$this->config['key_file']);
                $return = [
                    'paySign' => $signPay,
                    'nonceStr' => $noncestr,
                    'timeStamp' => $time,
                    'package' => $prepay,
                    'appid' => $appid,
                    'signType' => 'RSA'
                ];
            } else {
                return ['code' => 0, 'msg' => $dataArray['message']];
            }

        } catch (\Exception $exception) {
            return ['code' => 0, 'msg' => $exception->getMessage()];
        }
        return ['code' => 1, 'data' => $return];

    }
    public function mWechatpay($array, $openid,$title, $notify_url)
    {
        try {

            $appid = $this->config['sp_mchid'];//
            $mchid = $this->config['sp_mchid'];;// 服务商户id
            $subMchid = $this->config['sub_mchid'];//
            $xlid = $this->config['m_serial_number'];//证书序列号
            $time = time(); //时间戳
            $orderid = $array['sn_order'];//订单编号
            $noncestr = md5($orderid . $time . rand());//随机字符串，可以将订单编号存于此处
            $ordertotal = $array['reality_amount'] * 100;//
            $url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi";//生成预支序号所提交路径
            $urlarr = parse_url($url);
            $data = array();
            $data['sp_appid'] = $appid;
            $data['sp_mchid'] = strval($mchid);

            $data['sub_mchid'] = strval($subMchid);
            $data['description'] = $title;//商品描述
            $data['out_trade_no'] = $orderid;//订单编号
            $data['notify_url'] = getProtocol() . $_SERVER["HTTP_HOST"] . '/home.php/' . $notify_url;//回调接口，可以为空
            $data['amount']['total'] = (integer)$ordertotal;//金额 单位 分
            $data['amount']['currency'] = 'CNY';
            $data['payer']['sp_openid'] = $openid;//openid
            $jsonData = json_encode($data); //变为json格式
            $str = "POST" . "\n" . $urlarr['path'] . "\n" . $time . "\n" . $noncestr . "\n" . $jsonData . "\n";
            $signHead = $this->getPrivateSign($str,$this->config['m_key_file']);
            $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $noncestr, $time, $xlid, $signHead);
            $header = array(
                'Content-Type:application/json; charset=UTF-8',
                'Accept:application/json',
                'User-Agent:*/*',
                'Authorization: WECHATPAY2-SHA256-RSA2048  '. $token
            );
            $res = $this->httpRequest($url, $jsonData, $header);

            $dataArray = json_decode($res, true);
            if (isset($dataArray['prepay_id'])) {
                $prepayID = $dataArray['prepay_id'];
                $prepay = 'prepay_id=' . $prepayID;
                $str = $appid . "\n" . $time . "\n" . $noncestr . "\n" . $prepay . "\n";
                $signPay = $this->getPrivateSign($str,$this->config['m_key_file']);
                $return = [
                    'paySign' => $signPay,
                    'nonceStr' => $noncestr,
                    'timeStamp' => $time,
                    'package' => $prepay,
                    'appid' => $appid,
                    'signType' => 'RSA'
                ];
            } else {
                return ['code' => 0, 'msg' => $dataArray['message']];
            }

        } catch (\Exception $exception) {
            return ['code' => 0, 'msg' => $exception->getMessage()];
        }
        return ['code' => 1, 'data' => $return];


    }
    public function Message($openid, $data, $template_id)
    {
        /*try {*/
        $accessToken = $this->getAccessToken();

        $url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" . $accessToken;
        $param = [
           'access_token' => $accessToken,
            'touser' => $openid,
            'template_id' => $template_id,
            'data' => $data,
            'miniprogram_state' => 'formal',
            'lang' => 'zh_CN'

        ];
        $response = $this->json_post($url, $param);

        return $response;
    }
    public  function json_post($url, $data = NULL)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        if(!$data){
            return 'data is null';
        }
        if(is_array($data))
        {
            $data = json_encode($data);
        }
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_HTTPHEADER,array(
            'Content-Type: application/json; charset=utf-8',
            'Content-Length:' . strlen($data),
            'Cache-Control: no-cache',
            'Pragma: no-cache'
        ));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $res = curl_exec($curl);
        $errorno = curl_errno($curl);
        if ($errorno) {
            return $errorno;
        }
        curl_close($curl);
        return $res;

    }
    function getPrivateSign($content ,$keyFile)
    {
        $binary_signature = "";
        $privateKey = file_get_contents($keyFile);//证书
        $algo = "sha256WithRSAEncryption";

        //将上传内容与api证书结合生成签名
        openssl_sign($content, $binary_signature, $privateKey, $algo);

        return base64_encode($binary_signature);
    }
    public function httpRequest($url, $data, $header)
    {
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在，如果出错则修改为0，默认为1
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        }
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        if (!empty($header)) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $header);//$header以array格式
        }

        $response = curl_exec($curl); // 执行操作

        if (curl_errno($curl)) {
            echo 'Error:' . curl_error($curl);//捕抓异常
        }

        curl_close($curl); // 关闭CURL会话
        return $response; // 返回数据，json格式
    }

    // 获取用户信息
    public function getOpenidAndSessionKey($openid,$signature)
    {
        $access_token = $this->getAccessToken();
        $url_get =     "https://api.weixin.qq.com/wxa/business/getuserencryptkey?access_token=".$access_token."&signature=".$signature."&openid=".$openid."&sig_method=SIG_METHOD ";
        $data = curlGet($url_get);
        $output = json_decode($data, true);
        return $output;
    }

    // 获取用户信息
    public function getXcxUserInfo($code)
    {
        $url_get  =   "https://api.weixin.qq.com/sns/jscode2session?appid=".$this->config['appid']."&secret=".$this->config['appSecret']."&js_code=".$code."&grant_type=authorization_code";
        $data = curlGet($url_get);
        $output = json_decode($data, true);

        return $output;
    }

    public function withdrawal($openid, $data)
    {
        $post_data = [
            "appid" => $this->config['appid'],//appid
            "out_batch_no" => $data['sn_order'],//商家批次单号
            "batch_name" => '佣金提现',//批次名称
            "batch_remark" => '佣金提现',//批次备注
            "total_amount" => $data['amount'] * 100,// 转账金额单位为“分”
            "total_num" => 1, // 转账总笔数
            //此处可以多笔提现  组合二维数组放到transfer_detail_list即可   我这里单笔操作，写死了
            "transfer_detail_list" => [
                [
                    'out_detail_no' => $this->getOrderNumber(),
                    'transfer_amount' =>(integer) $data['amount'] * 100,
                    'transfer_remark' => '佣金提现',
                    'openid' => $openid,
                ]
            ]
        ];
        $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
        //JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE  防止中文被转义
        $nonce = md5($data['id'] . time() . rand());
        $timestamp = time();
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $param = json_encode($post_data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        //拼接参数
        $message = 'POST' . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $param . "\n";
        $sslKeyPath = $this->config['key_file'];
        $private_key = openssl_get_privatekey(file_get_contents($sslKeyPath));
        openssl_sign($message, $raw_sign, $private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%s",serial_no="%s",signature="%s"', $this->config['mchid'], $nonce, $timestamp, $this->config['serial_number'], $sign);
        $result = $this->wx_post($url, $param, $token);
        $result = json_decode($result, true);
        return $result;
    }

    private function wx_post($url, $param, $token)
    {

        $curl = curl_init();
        $headers = [
            'Authorization: ' . $token,
            'Accept:application/json',
            'Content-Type:application/json;charset=utf-8',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        ];
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $param);
        curl_setopt($curl, CURLOPT_POST, true);
        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }

    public function  templateId (){
        $accessToken = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token='.$accessToken ;
        $data = curlGet($url);
        $output = json_decode($data, true);
        if (isset($output['errcode'] ) && $output['errcode'] == '40001') {
            cache('access_token', null);
        }
        return $output;
    }

    public function getwxacode($invite){
        $accessToken = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$accessToken;
        $path = 'pages/index/index';

        $params = [
            'page' => $path,
            // 'access_token' => $accessToken,
            'scene' => 'invite='.$invite,
            'env_version' => 'trial'

        ];
        $data = curlPost($url,json_encode($params)) ;

        $base64_image ="data:image/jpeg;base64,".base64_encode( $data );
        return $base64_image;
    }

}